package com.xjscrm.console.web.chat;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.uzai.mobile.collect.api.MicaTopics;
import com.uzai.mobile.collect.api.dto.MicaTriggerDto;
import com.uzai.mobile.collect.api.dto.trigger.MicaTriggerForwardMultiRecordMsg;
import com.uzai.mobile.collect.api.dto.trigger.MicaTriggerMsgRecallMsg;
import com.uzai.mobile.collect.api.enums.MicaTriggerType;
import com.xjscrm.common.entity.*;
import com.xjscrm.common.exception.BusinessException;
import com.xjscrm.console.chat.cache.CacheHolder;
import com.xjscrm.console.chat.enums.ChatTalkRecordSource;
import com.xjscrm.console.chat.enums.MQMsgType;
import com.xjscrm.console.chat.frame.dto.ChatDeviceDTO;
import com.xjscrm.console.chat.frame.dto.ChatRecordDTO;
import com.xjscrm.console.chat.frame.dto.ChatSessionDTO;
import com.xjscrm.console.chat.frame.dto.ChatTagDTO;
import com.xjscrm.console.chat.frame.recv.*;
import com.xjscrm.console.chat.frame.send.*;
import com.xjscrm.console.chat.mq.MQSender;
import com.xjscrm.console.chat.mq.dto.SendDTO;
import com.xjscrm.console.chat.mq.dto.SendMQDTO;
import com.xjscrm.console.common.util.LoginContext;
import com.xjscrm.console.dto.chat.ChatCustomerDTO;
import com.xjscrm.console.dto.chat.ChatGroupDTO;
import com.xjscrm.console.dto.chat.ChatTalkRecordQueryDTO;
import com.xjscrm.console.entity.ChatTalkRecord;
import com.xjscrm.console.entity.ChatTalkSession;
import com.xjscrm.console.entity.ChatTalkSessionStaffRel;
import com.xjscrm.console.entity.MerchatChildDeviceRelation;
import com.xjscrm.console.mapper.StaffGroupMapper;
import com.xjscrm.console.mapper.WwGroupMemberMapper;
import com.xjscrm.console.mq.producer.SendMsgProducer;
import com.xjscrm.console.param.wwDevice.WwDeviceQuery;
import com.xjscrm.console.service.customer.chat.ChatTalkRecordService;
import com.xjscrm.console.service.customer.chat.ChatTalkSessionService;
import com.xjscrm.console.service.customer.chat.ChatTalkSessionStaffRelService;
import com.xjscrm.console.service.customer.childUser.ChildMerchatService;
import com.xjscrm.console.service.customer.group.WwGroupService;
import com.xjscrm.console.service.customer.merchat.MerchatChildDeviceRelationService;
import com.xjscrm.console.service.customer.wwCustomer.WwCustomerService;
import com.xjscrm.console.service.customer.wwDevice.WwDeviceService;
import com.xjscrm.console.vo.LoginVO;
import com.xjscrm.console.vo.chat.ChatGroupMemberVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.xjscrm.console.chat.core.impl.ChatRecallMsgHandler.RECALL_KEY;

/**
 * @author mingyang.chen create in 2024/3/15 11:54
 */
@Api(value = "聊天接口管理", tags = "客服聊天|聊天接口管理")
@RestController
@RequestMapping("/chat")
@Slf4j
public class ChatController {

    @Autowired
    private WwCustomerService wwCustomerService;
    @Autowired
    private ChatTalkSessionService chatTalkSessionService;
    @Autowired
    private WwDeviceService wwDeviceService;
    @Autowired
    private ChatTalkRecordService chatTalkRecordService;
    @Autowired
    private WwDeviceService deviceService;
    @Autowired
    private SendMsgProducer sendMsgProducer;
    @Autowired
    private WwGroupService wwGroupService;
    @Autowired
    private WwGroupMemberMapper wwGroupMemberMapper;
    @Autowired
    private ChatTalkSessionStaffRelService chatTalkSessionStaffRelService;
    @Autowired
    private MerchatChildDeviceRelationService merchatChildDeviceRelationService;
    @Autowired
    private WwCustomerService customerService;
    @Autowired
    private MerchatChildDeviceRelationService childDeviceRelationService;
    @Autowired
    private WwGroupService groupService;
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    private CacheHolder cacheHolder;
    @Autowired
    private ChildMerchatService childMerchatService;
    @Autowired
    private StaffGroupMapper staffGroupMapper;

    @PostMapping("/customer/detail")
    @ApiOperation(value = "客户资料", notes = "客户资料", response = SPullConversationResultMsg.class)
    public Object customerDetail(@RequestBody RPullConversationInfoMsg query) {
        if (Objects.isNull(query) || Objects.isNull(query.getTalkSessionId())) {
            throw new BusinessException("获取客户资料参数错误");
        }
        Long merId = LoginContext.getLogin().getMerId();
        Long talkSessionId = query.getTalkSessionId();

        ChatTalkSession byId = chatTalkSessionService.getById(merId, talkSessionId);
        if (Objects.isNull(byId)) {
            throw new BusinessException("获取客户资料失败: 会话不存在");
        }
        WwCustomer byWxId = wwCustomerService.getByWxId(byId.getMerId(), byId.getDeviceUniqueId(), byId.getConversationId());
        if (Objects.isNull(byWxId)) {
            throw new BusinessException("获取客户资料失败: 客户不存在");
        }
        SPullConversationResultMsg sPullConversationResultMsg = new SPullConversationResultMsg();
        BeanUtils.copyProperties(byWxId, sPullConversationResultMsg);

        chatTalkSessionService.fillTag(byId, tag -> {
            if (Objects.equals(tag.getType(), 1)) {
                sPullConversationResultMsg.getCompanyTags().add(
                        new ChatTagDTO(tag.getId(), tag.getTagName())
                );
            } else if (Objects.equals(tag.getType(), 2)) {
                sPullConversationResultMsg.getSelfTags().add(
                        new ChatTagDTO(tag.getId(), tag.getTagName())
                );
            }
        }, tag1 -> {
            sPullConversationResultMsg.getSelfTags().add(
                    new ChatTagDTO(tag1.getId(), tag1.getName())
            );
        });
        return sPullConversationResultMsg;
    }

    @PostMapping("/group/detail")
    @ApiOperation(value = "群聊资料", notes = "群聊资料", response = SPullGroupConversationResultMsg.class)
    public Object groupDetail(@RequestBody RPullGroupConversationInfoMsg query) {

        if (Objects.isNull(query) || Objects.isNull(query.getTalkSessionId())) {
            throw new BusinessException("获取群资料参数错误");
        }
        Long merId = LoginContext.getLogin().getMerId();


        ChatTalkSession byId = chatTalkSessionService.getById(merId, query.getTalkSessionId());
        if (Objects.isNull(byId)) {
            throw new BusinessException("获取群资料失败: 会话不存在");
        }
        WwGroup byGroupId = wwGroupService.getByGroupId(byId.getMerId(), byId.getDeviceUniqueId(), byId.getConversationId());
        if (Objects.isNull(byGroupId)) {
            throw new BusinessException("获取群资料失败: 群聊不存在");
        }

        SPullGroupConversationResultMsg pullGroupConversationResultMsg = new SPullGroupConversationResultMsg();
        BeanUtils.copyProperties(byGroupId, pullGroupConversationResultMsg);
        //
        chatTalkSessionService.fillTag(byId, tag -> {
            ChatTagDTO chatTagDTO = new ChatTagDTO(tag.getId(), tag.getTagName());
            pullGroupConversationResultMsg.getTags().add(chatTagDTO);
        }, tag1 -> {
            ChatTagDTO chatTagDTO = new ChatTagDTO(tag1.getId(), tag1.getName());
            pullGroupConversationResultMsg.getTags().add(chatTagDTO);
        });

        //
        String createWxid = byGroupId.getCreateWxid();
        String r = byGroupId.getAdminWxIds();
        if (StringUtils.isNotBlank(r)) {
            try {
                List<String> adminWxIds = JSON.parseArray(r, String.class);
                if (ObjectUtils.isNotEmpty(adminWxIds)) {
                    adminWxIds.add(createWxid);
                }
                //
                List<WwGroupMember> groupMembers = wwGroupMemberMapper.selectListByGroupWxIdAndWxid(byGroupId.getGroupWxid(), adminWxIds, merId);
                adminWxIds.remove(createWxid);
                if (ObjectUtils.isNotEmpty(groupMembers)) {
                    Map<String, WwGroupMember> collect = groupMembers.stream().collect(Collectors.toMap(WwGroupMember::getWxid, Function.identity()));

                    for (String adminWxId : adminWxIds) {
                        WwGroupMember wwGroupMember = collect.get(adminWxId);

                        SPullGroupConversationResultMsg.GroupAdminItem groupAdminItem = new SPullGroupConversationResultMsg.GroupAdminItem();
                        groupAdminItem.setAdminWxName(wwGroupMember.getNick());
                        groupAdminItem.setAdminWxId(wwGroupMember.getWxid());
                        groupAdminItem.setHeadImageUrl(wwGroupMember.getHimg());

                        pullGroupConversationResultMsg.getAdmins().add(groupAdminItem);
                    }

                    WwGroupMember createGroupMember = collect.get(createWxid);
                    if (Objects.nonNull(createGroupMember)) {
                        pullGroupConversationResultMsg.setCreateWxName(createGroupMember.getNick());
                    }
                }
            } catch (Exception e) {
                log.error("解析群管理员json出错");
            }
        }
        return pullGroupConversationResultMsg;
    }

    @PostMapping("/recently_session/list")
    @ApiOperation(value = "最近聊天列表", notes = "最近聊天列表", response = ChatSessionDTO.class)
    public Object recentlySessionPage(@RequestBody RPullSessionMsg content) {

        Page<ChatSessionDTO> result = new Page<>(content.getCurrent(), content.getSize());
        try {
            Long merId = content.getMerId();
            Long deviceUniqueId = content.getDeviceUniqueId();
            if (Objects.nonNull(content.getSearchStaffId())) {
                List<ChatTalkSessionStaffRel> chatTalkSessionStaffRels = chatTalkSessionStaffRelService.listByStaffId(merId, content.getSearchStaffId());
                if (ObjectUtils.isNotEmpty(chatTalkSessionStaffRels)) {
                    List<Long> sessionIds = chatTalkSessionStaffRels.stream().map(ChatTalkSessionStaffRel::getTalkSessionId).distinct().collect(Collectors.toList());
                    content.setSessionIds(sessionIds);
                }
            }
            //
            Page<ChatTalkSession> sessionPage = chatTalkSessionService.page(merId, content);

            if (ObjectUtils.isEmpty(sessionPage.getRecords())) {
                return result;
            }
            //
            List<Long> sessionIds = sessionPage.getRecords().stream().map(ChatTalkSession::getId).distinct().collect(Collectors.toList());

            // 查询机器人关联的回话
            List<ChatTalkSessionStaffRel> sessionStaffRelList = chatTalkSessionStaffRelService.listBySessionIds(content.getMerId(), content.getStaffId(), sessionIds);
            Map<Long, ChatTalkSessionStaffRel> collect = sessionStaffRelList.stream().collect(Collectors.toMap(ChatTalkSessionStaffRel::getTalkSessionId, Function.identity()));

            List<ChatSessionDTO> resultRecords = new ArrayList<>();
            for (ChatTalkSession record : sessionPage.getRecords()) {
                ChatSessionDTO chatSessionDTO = new ChatSessionDTO();
                BeanUtils.copyProperties(record, chatSessionDTO);
                if (collect.containsKey(record.getId())) {
                    chatSessionDTO.setChat(1);
                }
                chatTalkSessionService.fillConversationName(record, chatSessionDTO);
                resultRecords.add(chatSessionDTO);
            }

            result.setRecords(resultRecords);
            result.setTotal(sessionPage.getTotal());
        } catch (Exception e) {
            log.error("拉取机器人最近会话失败", e);
            throw new BusinessException("拉取机器人最近会话失败");
        }
        return result;
    }

    @PostMapping("/customer/list")
    @ApiOperation(value = "好友列表", notes = "好友列表", response = ChatCustomerDTO.class)
    public Object customerList(@RequestBody RPullCustomerMsg content) {
        LoginVO login = LoginContext.getLogin();
        Long merId = login.getMerId();
        Long staffId = login.getId();

        if (Objects.equals(merId, staffId)) {
            throw new BusinessException("主账号不支持操作");
        }
        Page<ChatCustomerDTO> result = new Page<>(content.getCurrent(), content.getSize());

        try {
            List<Long> deviceUniqueIds;
            //
            if (Objects.isNull(content.getDeviceUniqueId())) {
                List<MerchatChildDeviceRelation> merchatChildDeviceRelations = childDeviceRelationService.listByStaffId(merId, staffId);
                if (ObjectUtils.isEmpty(merchatChildDeviceRelations)) {
                    return merchatChildDeviceRelations;
                }
                deviceUniqueIds = merchatChildDeviceRelations.stream().map(MerchatChildDeviceRelation::getRobotId).distinct().collect(Collectors.toList());
            } else {
                deviceUniqueIds = Lists.newArrayList(content.getDeviceUniqueId());
            }
            content.setDeviceUniqueIds(deviceUniqueIds);

            //
            Page<WwCustomer> customerList = customerService.pageFromChat(merId, content);
            if (ObjectUtils.isEmpty(customerList.getRecords())) {
                return result;
            }
            Map<Long, List<WwCustomer>> deviceUniqueIdCustomerMap = customerList.getRecords().stream().collect(Collectors.groupingBy(WwCustomer::getDeviceUniqueId));

            List<ChatCustomerDTO> resultRecords = new ArrayList<>();

            for (Map.Entry<Long, List<WwCustomer>> deviceUniqueIdCustomerEntry : deviceUniqueIdCustomerMap.entrySet()) {
                Long deviceUniqueId = deviceUniqueIdCustomerEntry.getKey();
                List<String> conversationIds = deviceUniqueIdCustomerEntry.getValue().stream().map(WwCustomer::getWxid).distinct().collect(Collectors.toList());
                //
                Map<String, Long> sessionIdConversationCache = chatTalkSessionService.listByConversationIds(merId, deviceUniqueId, conversationIds)
                        .stream().collect(Collectors.toMap(ChatTalkSession::getConversationId, ChatTalkSession::getId));

                List<Long> collect = chatTalkSessionStaffRelService.listIdsBySessionIds(merId, staffId, new ArrayList<>(sessionIdConversationCache.values()));

                for (WwCustomer record : deviceUniqueIdCustomerEntry.getValue()) {
                    ChatCustomerDTO chatCustomerDTO = new ChatCustomerDTO();

                    chatCustomerDTO.setHeadImgUrl(record.getHeadImgUrl());
                    chatCustomerDTO.setName(record.getName());
                    chatCustomerDTO.setWxId(record.getWxid());
                    chatCustomerDTO.setCorpId(record.getCorpId());
                    chatCustomerDTO.setId(record.getId());
                    chatCustomerDTO.setDeviceUniqueId(deviceUniqueId);

                    if (sessionIdConversationCache.containsKey(record.getWxid())) {
                        Long talkSessionId = sessionIdConversationCache.get(record.getWxid());
                        if (collect.contains(talkSessionId)) {
                            chatCustomerDTO.setChat(1);
                            chatCustomerDTO.setTalkSessionId(talkSessionId);
                        }
                    }
                    resultRecords.add(chatCustomerDTO);
                }
            }
            //
            result.setRecords(resultRecords);
            result.setTotal(customerList.getTotal());
        } catch (Exception e) {
            log.error("拉取机器人客户失败", e);
            throw new BusinessException("拉取机器人客户失败");
        }
        return result;
    }

    @PostMapping("/device/list")
    @ApiOperation(value = "设备列表", notes = "设备列表", response = ChatDeviceDTO.class)
    public Object deviceList() {
        LoginVO login = LoginContext.getLogin();
        Long merId = login.getMerId();
        Long staffId = login.getId();


        try {
            List<WwDevice> devices;
            if (Objects.equals(merId, staffId)) {
                List<WwDevice> wwDevices = deviceService.listByMerId(merId);
                if (ObjectUtils.isEmpty(wwDevices)) {
                    return Lists.newArrayList();
                }
                devices = wwDevices;

            } else {
                List<MerchatChildDeviceRelation> merchatChildDeviceRelations = merchatChildDeviceRelationService.listByStaffId(merId, staffId);
                if (ObjectUtils.isEmpty(merchatChildDeviceRelations)) {
                    return Lists.newArrayList();
                }
                List<Long> deviceUniqueIds = merchatChildDeviceRelations.stream().map(MerchatChildDeviceRelation::getRobotId).distinct().collect(Collectors.toList());
                WwDeviceQuery wwDeviceQuery = new WwDeviceQuery();
                wwDeviceQuery.setMerId(merId);
                wwDeviceQuery.setDeviceUniqueIds(deviceUniqueIds);
                devices = deviceService.listByCondition(wwDeviceQuery);
            }

            if (ObjectUtils.isEmpty(devices)) {
                return Lists.newArrayList();
            }
            List<ChatDeviceDTO> deviceMsgs = new ArrayList<>();
            for (WwDevice device : devices) {
                ChatDeviceDTO sDeviceMsg = new ChatDeviceDTO();
                BeanUtils.copyProperties(device, sDeviceMsg);

                deviceMsgs.add(sDeviceMsg);
            }
            return deviceMsgs;
        } catch (Exception e) {
            log.error("获取设备列表失败", e);
            throw new BusinessException("获取设备列表失败");
        }
    }

    @PostMapping("/group/list")
    @ApiOperation(value = "群聊列表", notes = "群聊列表", response = ChatGroupDTO.class)
    public Object groupList(@RequestBody RPullGroupMsg content) {

        LoginVO login = LoginContext.getLogin();
        Long merId = login.getMerId();
        Long staffId = login.getId();

        if (Objects.equals(merId, staffId)) {
            throw new BusinessException("主账号不支持操作");
        }
        Page<ChatGroupDTO> result = new Page<>(content.getCurrent(), content.getSize());
        try {

            List<Long> deviceUniqueIds;
            //
            if (Objects.isNull(content.getDeviceUniqueId())) {
                List<MerchatChildDeviceRelation> merchatChildDeviceRelations = childDeviceRelationService.listByStaffId(merId, staffId);
                if (ObjectUtils.isEmpty(merchatChildDeviceRelations)) {
                    return merchatChildDeviceRelations;
                }
                deviceUniqueIds = merchatChildDeviceRelations.stream().map(MerchatChildDeviceRelation::getRobotId).distinct().collect(Collectors.toList());
            } else {
                deviceUniqueIds = Lists.newArrayList(content.getDeviceUniqueId());
            }
            content.setDeviceUniqueIds(deviceUniqueIds);

            Page<WwGroup> customerList = groupService.pageFromChat(merId, content);
            if (ObjectUtils.isEmpty(customerList.getRecords())) {
                return result;
            }
            Map<Long, List<WwGroup>> deviceUniqueIdGroupMap = customerList.getRecords().stream().collect(Collectors.groupingBy(WwGroup::getDeviceUniqueId));

            List<ChatGroupDTO> resultRecords = new ArrayList<>();
            for (Map.Entry<Long, List<WwGroup>> deviceUniqueIdGroupEntry : deviceUniqueIdGroupMap.entrySet()) {
                Long deviceUniqueId = deviceUniqueIdGroupEntry.getKey();
                //
                List<String> conversationIds = deviceUniqueIdGroupEntry.getValue().stream().map(WwGroup::getGroupWxid).distinct().collect(Collectors.toList());
                Map<String, Long> sessionIdConversationCache = chatTalkSessionService.listByConversationIds(merId, deviceUniqueId, conversationIds)
                        .stream().collect(Collectors.toMap(ChatTalkSession::getConversationId, ChatTalkSession::getId));

                List<Long> collect = chatTalkSessionStaffRelService.listIdsBySessionIds(merId, login.getId(), new ArrayList<>(sessionIdConversationCache.values()));

                for (WwGroup record : deviceUniqueIdGroupEntry.getValue()) {
                    ChatGroupDTO chatCustomerDTO = new ChatGroupDTO();

                    chatCustomerDTO.setGroupName(record.getGroupName());
                    chatCustomerDTO.setGroupWxId(record.getGroupWxid());
                    chatCustomerDTO.setId(record.getId());
                    chatCustomerDTO.setDeviceUniqueId(deviceUniqueId);
                    if (sessionIdConversationCache.containsKey(record.getGroupWxid())) {
                        Long talkSessionId = sessionIdConversationCache.get(record.getGroupWxid());
                        if (collect.contains(talkSessionId)) {
                            chatCustomerDTO.setChat(1);
                            chatCustomerDTO.setTalkSessionId(talkSessionId);
                        }
                    }
                    resultRecords.add(chatCustomerDTO);
                }
            }
            result.setRecords(resultRecords);
            result.setTotal(customerList.getTotal());
        } catch (Exception e) {
            log.error("拉取机器人群聊失败", e);
            throw new BusinessException("拉取机器人群聊失败");
        }
        return result;
    }

    @PostMapping("/group/members/list")
    @ApiOperation(value = "群聊成员列表", notes = "群聊成员列表", response = ChatGroupMemberVO.class)
    public Object groupMembersList(@RequestBody RPullGroupMemberMsg content) {

        LoginVO login = LoginContext.getLogin();
        Long talkSessionId = content.getTalkSessionId();

        ChatTalkSession byId = chatTalkSessionService.getById(login.getMerId(), talkSessionId);
        if (Objects.isNull(byId)) {
            throw new BusinessException("获取群资料失败: 会话不存在");
        }

        WwGroup group = groupService.getByGroupId(content.getMerId(), byId.getDeviceUniqueId(), byId.getConversationId());
        if (Objects.isNull(group)) {
            throw new BusinessException("群聊信息丢失, 请稍后重试!");
        }
        String ownerWxId = group.getCreateWxid();
        List<String> adminWxIds = null;
        boolean hasAdmin = false;
        if (StringUtils.isNotBlank(group.getAdminWxIds())) {
            adminWxIds = JSON.parseArray(group.getAdminWxIds(), String.class);
            hasAdmin = true;
        }
        //
        Page<WwGroupMember> memberList = groupService.listMembersFromChat(content);

        List<ChatGroupMemberVO> resultRecord = new ArrayList<>();
        for (WwGroupMember record : memberList.getRecords()) {

            ChatGroupMemberVO chatGroupMemberVO = new ChatGroupMemberVO();
            chatGroupMemberVO.setWxid(record.getWxid());
            chatGroupMemberVO.setNick(record.getNick());
            chatGroupMemberVO.setHeadImgUrl(record.getHimg());
            chatGroupMemberVO.setCorpId(record.getCorpId());
            chatGroupMemberVO.setCorpId(record.getCorpId());
            chatGroupMemberVO.setOwner(StringUtils.equals(record.getWxid(), ownerWxId) ? 1 : 0);
            if (hasAdmin) {
                chatGroupMemberVO.setAdmin(adminWxIds.contains(record.getWxid()) ? 1 : 0);
            }
            resultRecord.add(chatGroupMemberVO);
        }

        return new Page<ChatGroupMemberVO>(memberList.getCurrent(), memberList.getSize(), memberList.getTotal()).setRecords(resultRecord);
    }

    @PostMapping("/session/record/list")
    @ApiOperation(value = "聊天记录", notes = "聊天记录", response = ChatRecordDTO.class)
    public Object sessionRecord(@RequestBody RPullRecordMsg content) {

        LoginVO login = LoginContext.getLogin();
        try {

            Long merId = login.getMerId();
            Long talkSessionId = content.getTalkSessionId();

            ChatTalkSession talkSession = chatTalkSessionService.getById(merId, talkSessionId);
            if (Objects.isNull(talkSession)) {
                throw new BusinessException("聊天记录拉取失败: 会话未找到");
            }
            boolean isGroup = Objects.equals(talkSession.getType(), 111);
            String conversationId = talkSession.getConversationId();

            WwCustomer customer;
            if (!isGroup) {
                customer = wwCustomerService.getByWxId(merId, talkSession.getDeviceUniqueId(), conversationId);
            } else {
                customer = new WwCustomer();
            }

            ChatTalkRecordQueryDTO query = new ChatTalkRecordQueryDTO();
            query.setMerId(content.getMerId());
            query.setTalkSessionId(talkSessionId);
            query.setPullCount(content.getPullCount());
            query.setPullTime(content.getPullTime());
            query.setContentType(content.getContentType());
            query.setKeyword(content.getKeyword());
            List<ChatTalkRecord> pullRecords = chatTalkRecordService.listByTime(query);

            if (ObjectUtils.isEmpty(pullRecords)) {
                return Lists.newArrayList();
            }
            Map<String, WwGroupMember> collect = new HashMap<>();
            if (isGroup) {
                List<String> wxIds = pullRecords.stream().map(ChatTalkRecord::getSendWxId).distinct().collect(Collectors.toList());
                List<WwGroupMember> wwGroupMembers = wwGroupMemberMapper.selectListByGroupWxIdAndWxid(talkSession.getConversationId(), wxIds, merId);
                collect = wwGroupMembers.stream().collect(Collectors.toMap(WwGroupMember::getWxid, Function.identity()));
            }

            Map<String, WwGroupMember> finalCollect = collect;
            List<ChatRecordDTO> result = pullRecords.stream().map(item -> {
                ChatRecordDTO chatRecordDTO = new ChatRecordDTO();
                BeanUtils.copyProperties(item, chatRecordDTO);
                chatRecordDTO.parse();
                if (isGroup) {
                    WwGroupMember wwGroupMember = finalCollect.get(item.getSendWxId());
                    if (Objects.nonNull(wwGroupMember)) {
                        chatRecordDTO.setHeadImgUrl(wwGroupMember.getHimg());
                        chatRecordDTO.setSendWxName(wwGroupMember.getNick());
                    }
                } else {
                    if (Objects.nonNull(customer)) {
                        chatRecordDTO.setHeadImgUrl(customer.getHeadImgUrl());
                        if (StringUtils.isBlank(chatRecordDTO.getSendWxName())) {
                            chatRecordDTO.setSendWxName(customer.getNickname());
                        }
                    }
                }
                return chatRecordDTO;
            }).collect(Collectors.toList());

            return result;
        } catch (Exception e) {
            log.error("拉取回话聊天记录失败", e);
            throw new BusinessException("拉取回话聊天记录失败");
        }
    }


    @PostMapping("/session/record/forward")
    @ApiOperation(value = "转发消息", notes = "转发消息", response = Boolean.class)
    public Object sessionRecord(@RequestBody RForwardMultiRecordMsg content) {

        LoginVO login = LoginContext.getLogin();
        Long merId = login.getMerId();
        List<Long> recordIds = content.getRecordIds();
        Long talkSessionId = content.getTalkSessionId();
        Long deviceUniqueId = content.getDeviceUniqueId();
        List<String> recvWxIds = content.getRecvWxIds();

        try {
            WwDevice byId = deviceService.getById(merId, deviceUniqueId);
            if (Objects.isNull(byId)) {
                throw new BusinessException("机器人设备未找到");
            }
            //
            List<ChatTalkRecord> chatTalkRecords = chatTalkRecordService.listByIds(merId, recordIds, talkSessionId);
            if (ObjectUtils.isEmpty(chatTalkRecords)) {
                return SResultMsg.fail(content, "批量转发失败: 聊天记录不存在");
            }
            ChatTalkSession talkSession = chatTalkSessionService.getById(merId, talkSessionId);
            if (Objects.isNull(talkSession)) {
                return SResultMsg.fail(content, "批量转发失败: 会话不存在");
            }

            List<Long> msgIds = chatTalkRecords.stream().map(ChatTalkRecord::getRemoteMsgId).collect(Collectors.toList());

            MicaTriggerForwardMultiRecordMsg micaTriggerForwardMultiRecordMsg = new MicaTriggerForwardMultiRecordMsg();

            micaTriggerForwardMultiRecordMsg.setMsgId(msgIds);
            micaTriggerForwardMultiRecordMsg.setConversationId(talkSession.getConversationId());
            micaTriggerForwardMultiRecordMsg.setWxIds(recvWxIds);

            MicaTriggerDto micaTriggerDto = MicaTriggerDto.newInstance(micaTriggerForwardMultiRecordMsg, MicaTriggerType.TRIGGER_FORWARD_MULTI_RECORD, item -> {
                item.setReqId(IdUtil.getSnowflakeNextId());
                item.setDeviceId(byId.getDeviceId());
                item.setDeviceType(byId.getDeviceType());
            });
            sendMsgProducer.pushMsg(micaTriggerDto, MicaTopics.WW_TRIGGER_TOPIC);
            return true;
        } catch (Exception e) {
            log.error("批量转发消息失败", e);
            throw new BusinessException("批量转发消息失败");
        }
    }

    @PostMapping("/session/record/recall")
    @ApiOperation(value = "撤回消息", notes = "撤回消息", response = Boolean.class)
    public Object sessionRecord(@RequestBody RRecallMsg content) {
        try {

            ChatTalkSession talkSession = chatTalkSessionService.getById(content.getMerId(), content.getTalkSessionId());

            if (Objects.isNull(talkSession)) {
                throw new BusinessException("会话信息不存在, 请刷新后重试");
            }
            ChatTalkRecord talkRecord = chatTalkRecordService.getById(content.getMerId(), content.getRecordId());
            if (Objects.isNull(talkRecord) || Objects.isNull(talkRecord.getRemoteMsgId())) {
                throw new BusinessException("聊天记录数据错误");
            }
            if (!Objects.equals(talkRecord.getSource(), ChatTalkRecordSource.reply.getCode())) {
                throw new BusinessException("非回复消息, 不支持撤回");
            }
            int now = (int) (System.currentTimeMillis() / 1000L);
            if (Objects.isNull(talkRecord.getWxSendTime())) {
                throw new BusinessException("回复消息数据错误");
            }
            if (now - talkRecord.getWxSendTime() > 120) {
                throw new BusinessException("回复时间超过了两分钟不支持撤回");
            }

            MicaTriggerMsgRecallMsg msgRecallMsg = new MicaTriggerMsgRecallMsg();
            msgRecallMsg.setMsgRemoteId(String.valueOf(talkRecord.getRemoteMsgId()));
            msgRecallMsg.setMessageId(talkRecord.getId());

            // 构建trigger对象
            MicaTriggerDto micaTriggerDto = MicaTriggerDto.newInstance(msgRecallMsg, MicaTriggerType.TRIGGER_MSG_RECALL, item -> {
                item.setReqId(msgRecallMsg.getMessageId());
                item.setDeviceId(talkSession.getDeviceId());
                item.setDeviceType(talkSession.getDeviceType());
            });
            sendMsgProducer.pushMsg(micaTriggerDto, MicaTopics.WW_TRIGGER_TOPIC);

            //
            redisTemplate.opsForValue().set(String.format(RECALL_KEY, talkRecord.getId()), talkRecord.getId(), 5, TimeUnit.MINUTES);

            return true;
        } catch (Exception e) {
            log.error("消息撤回失败", e);
            throw new BusinessException("消息撤回失败, 请稍后重试");
        }
    }

    @PostMapping("/session/list")
    @ApiOperation(value = "回话列表", notes = "回话列表", response = ChatSessionDTO.class)
    public Object sessionList(@RequestBody RPullTalkSessionMsg content) {

        LoginVO login = LoginContext.getLogin();

        Long merId = login.getMerId();
        Long staffId = login.getId();
        Long deviceUniqueId = content.getDeviceUniqueId();

        try {
            Page<ChatTalkSessionStaffRel> page = new Page<>(content.getCurrent(), content.getSize());
            // 查询机器人关联的回话
            List<ChatTalkSessionStaffRel> sessionStaffRelList;
            ChatTalkSessionStaffRel query = new ChatTalkSessionStaffRel();
            query.setMerId(merId);
            query.setStaffId(staffId);
            query.setHang(content.getHang());
            if (Objects.nonNull(deviceUniqueId)) {
                query.setDeviceUniqueId(deviceUniqueId);
                sessionStaffRelList = chatTalkSessionStaffRelService.pageByCondition(query, page);
            } else {
                sessionStaffRelList = chatTalkSessionStaffRelService.pageByCondition(query, page);
            }
            if (ObjectUtils.isEmpty(sessionStaffRelList)) {
                return new Page<>(page.getCurrent(), page.getSize(), 0);
            }

            List<ChatSessionDTO> sessionMsgs = new ArrayList<>(sessionStaffRelList.size());

            for (ChatTalkSessionStaffRel sessionStaffRel : sessionStaffRelList) {
                //
                ChatTalkSession talkSession = chatTalkSessionService.getById(merId, sessionStaffRel.getTalkSessionId());
                if (Objects.nonNull(talkSession) && Objects.equals(talkSession.getOpenShield(), 1)) {
                    continue;
                }
                WwDevice wwDevice = wwDeviceService.getById(merId, talkSession.getDeviceUniqueId());

                Integer lastReadTime = talkSession.getLastReadTime();
                Integer noReadCount;
                if (Objects.isNull(lastReadTime)) {
                    noReadCount = chatTalkRecordService.countWithNoRead(merId, sessionStaffRel.getTalkSessionId(), null);
                } else {
                    noReadCount = chatTalkRecordService.countWithNoRead(merId, sessionStaffRel.getTalkSessionId(), lastReadTime);
                }

                ChatSessionDTO talkSessionMsg = chatTalkSessionService.convert(talkSession);

                talkSessionMsg.setDeviceName(wwDevice.getDeviceName());
                talkSessionMsg.setOpenPinTop(sessionStaffRel.getOpenPinTop());
                talkSessionMsg.setOpenPinTopTime(sessionStaffRel.getOpenPinTopTime());
                talkSessionMsg.setOpenSilence(sessionStaffRel.getOpenSilence());
                talkSessionMsg.setOpenSilenceTime(sessionStaffRel.getOpenSilenceTime());
                talkSessionMsg.setExpire(sessionStaffRel.getExpire());
                talkSessionMsg.setExpireTime(sessionStaffRel.getExpireTime());
                talkSessionMsg.setShowExpireTime(sessionStaffRel.getShowExpireTime());
                talkSessionMsg.setEnd(sessionStaffRel.getEnd());
                talkSessionMsg.setEndTime(sessionStaffRel.getEndTime());
                talkSessionMsg.setHang(sessionStaffRel.getHang());
                talkSessionMsg.setTransfer(sessionStaffRel.getTransfer());
                talkSessionMsg.setAuto(sessionStaffRel.getAuto());

//                chatTalkSessionService.fillTag(talkSession, tag -> {
//                    if (Objects.equals(tag.getType(), 1)) {
//                        talkSessionMsg.getCompanyTagIds().add(tag.getId());
//                    } else if (Objects.equals(tag.getType(), 1)) {
//                        talkSessionMsg.getSelfTagIds().add(tag.getId());
//                    }
//                }, tag1 -> {
//                    talkSessionMsg.getSelfTagIds().add(tag1.getId());
//                });
//
//                chatTalkSessionService.fillConversationName(talkSession, talkSessionMsg);

                talkSessionMsg.setNoReadCount(noReadCount);
                talkSessionMsg.setLastReadTime(lastReadTime);
                talkSessionMsg.setLastTalkRecord(this.doLoadTalkRecord(merId, talkSession.getLastRecvId()));
                talkSessionMsg.setExpire(sessionStaffRel.getExpire());
                talkSessionMsg.setExpireTime(sessionStaffRel.getExpireTime());
                talkSessionMsg.setShowExpireTime(sessionStaffRel.getShowExpireTime());
                talkSessionMsg.setShowExpireTime(sessionStaffRel.getShowExpireTime());
                sessionMsgs.add(talkSessionMsg);
            }
            return new Page<ChatSessionDTO>(page.getCurrent(), page.getSize(), page.getTotal()).setRecords(sessionMsgs);
        } catch (Exception e) {
            log.error("拉取机器人回话失败", e);
            throw new BusinessException("拉取机器人回话失败");
        }
    }

    private ChatRecordDTO doLoadTalkRecord(Long merId, Long lastTalkId) {
        ChatTalkRecordQueryDTO chatTalkRecordQuery = new ChatTalkRecordQueryDTO();
        chatTalkRecordQuery.setId(lastTalkId);
        chatTalkRecordQuery.setMerId(merId);
        ChatTalkRecord chatTalkRecord = chatTalkRecordService.loadLastTalk(chatTalkRecordQuery);
        if (Objects.isNull(chatTalkRecord)) {
            return null;
        }
        ChatRecordDTO chatRecordDTO = new ChatRecordDTO();
        BeanUtils.copyProperties(chatTalkRecord, chatRecordDTO);
        chatRecordDTO.parse();
        return chatRecordDTO;
    }

    @PostMapping("/session/hang")
    @ApiOperation(value = "会话挂起", notes = "会话挂起", response = Boolean.class)
    public Object sessionHang(@RequestBody RSessionHangMsg content) {

        if (Objects.isNull(content) || Objects.isNull(content.getMerId()) || Objects.isNull(content.getTalkSessionId()) || Objects.isNull(content.getOptType())) {
            throw new BusinessException("会话挂起参数错误");
        }
        Long merId = content.getMerId();
        Long staffId = content.getStaffId();
        Long talkSessionId = content.getTalkSessionId();
        Long optType = content.getOptType();

        //
        ChatTalkSession talkSession = chatTalkSessionService.getById(merId, talkSessionId);
        if (Objects.isNull(talkSession)) {
            throw new BusinessException("会话挂起失败: 会话不存在");
        }
        if (Objects.equals(talkSession.getOpenShield(), 1)) {
            throw new BusinessException("会话挂起失败: 会话已屏蔽");
        }
        ChatTalkSessionStaffRel bySessionId = chatTalkSessionStaffRelService.getBySessionId(merId, staffId, talkSession.getDeviceUniqueId(), talkSessionId);
        if (Objects.isNull(bySessionId)) {
            throw new BusinessException("会话挂起失败: 会话未分配员工");
        }
        Integer hangCount = chatTalkSessionStaffRelService.countHangWithStaffId(merId, staffId);
        if (Objects.equals(optType, 1L) && hangCount >= 50) {
            throw new BusinessException("会话挂起失败: 当前账号挂起会话已超过50");
        }
        ChatTalkSessionStaffRel update = new ChatTalkSessionStaffRel();
        update.setId(bySessionId.getId());
        update.setMerId(bySessionId.getMerId());
        update.setHang(Objects.equals(optType, 0L) ? 0 : 1);
        update.setUpdateTime((int) (System.currentTimeMillis() / 1000L));
        chatTalkSessionStaffRelService.updateById(update);
        // 清除掉会话相关的定时任务
        chatTalkSessionService.delChatRecvDelayTask(merId, staffId, talkSession);
        chatTalkSessionService.delChatCleanDelayTask(merId, staffId, talkSession);
        // 刷新会话数量
        chatTalkSessionStaffRelService.refreshStaffSessionCount(merId, staffId);
        return true;
    }

    @PostMapping("/session/transfer")
    @ApiOperation(value = "会话转交", notes = "会话转交", response = Boolean.class)
    public Object sessionTransfer(@RequestBody RSessionTransferMsg content) {

        if (Objects.isNull(content) || Objects.isNull(content.getMerId()) || Objects.isNull(content.getTalkSessionId()) || Objects.isNull(content.getTransferStaffId())) {
            throw new BusinessException("会话转交参数错误");
        }
        Long merId = content.getMerId();
        Long staffId = content.getStaffId();
        Long talkSessionId = content.getTalkSessionId();
        Long transferStaffId = content.getTransferStaffId();
        ChatTalkSession talkSession = chatTalkSessionService.getById(merId, talkSessionId);
        if (Objects.isNull(talkSession)) {
            throw new BusinessException("会话转交失败: 会话不存在");
        }
        if (Objects.equals(talkSession.getOpenShield(), 1)) {
            throw new BusinessException("会话转交失败: 会话已屏蔽");
        }
        ChatTalkSessionStaffRel bySessionId = chatTalkSessionStaffRelService.getBySessionId(merId, staffId, talkSession.getDeviceUniqueId(), talkSessionId);
        if (Objects.nonNull(bySessionId) && !Objects.equals(bySessionId.getStaffId(), staffId)) {
            throw new BusinessException("会话转交失败: 会话已分配员工");
        }
        if (Objects.equals(bySessionId.getStaffId(), transferStaffId)) {
            throw new BusinessException("会话转交失败: 不能转交给自己");
        }
        String staffTag = cacheHolder.getStaffTag(transferStaffId);
        if (StringUtils.isBlank(staffTag)) {
            throw new BusinessException("会话转交失败: 转交员工不在线");
        }
        ChatTalkSessionStaffRel update = new ChatTalkSessionStaffRel();
        update.setId(bySessionId.getId());
        update.setMerId(bySessionId.getMerId());
        update.setStaffId(transferStaffId);
        update.setTransfer(1);
        update.setUpdateTime((int) (System.currentTimeMillis() / 1000L));
        chatTalkSessionStaffRelService.updateById(update);
        // 清除掉会话相关的定时任务
        chatTalkSessionService.delChatRecvDelayTask(merId, staffId, talkSession);
        chatTalkSessionService.delChatCleanDelayTask(merId, staffId, talkSession);

        // 推送消息
        SendDTO sendDTO = new SendDTO();
        sendDTO.setStaffId(transferStaffId);
        sendDTO.setTalkSessionId(talkSessionId);
        sendDTO.setTalkRecordId(talkSession.getLastRecvId());
        sendDTO.setMerId(merId);
        sendDTO.setStaffTag(staffTag);

        SendMQDTO sendMQDTO = new SendMQDTO();
        sendMQDTO.setType(MQMsgType.push_talk.getCode());
        sendMQDTO.setData(sendDTO);

        MQSender.sendMQMsg("XJ_WW_DISPATCH_HANDLE_TOPIC:" + staffTag, sendMQDTO);
        chatTalkSessionStaffRelService.refreshStaffSessionCount(merId, staffId);
        return true;
    }

    @PostMapping("/staff/list")
    @ApiOperation(value = "获取当前机器人关联的员工列表", notes = "获取当前机器人关联的员工列表", response = SGetStaffListResultMsg.StaffItem.class)
    public Object sessionTransfer(@RequestBody RGetStaffListMsg content) {

        if (Objects.isNull(content) || Objects.isNull(content.getDeviceUniqueId())) {
            throw new BusinessException("请选择机器人后再操作");
        }
        Long merId = content.getMerId();
        Long staffGroupId = content.getStaffGroupId();
        List<Long> ids = merchatChildDeviceRelationService.listStaffIdsByDeviceUniqueId(merId, content.getDeviceUniqueId());
        if (ObjectUtils.isEmpty(ids)) {
            return Lists.newArrayList();
        }
        ids.remove(content.getStaffId());
        if (ObjectUtils.isEmpty(ids)) {
            return Lists.newArrayList();
        }
        List<MerchatChild> merchatChildList = childMerchatService.listByIdsAndGroupId(merId, ids, staffGroupId);
        if (ObjectUtils.isNotEmpty(merchatChildList)) {
            return merchatChildList.stream().map(item -> {

                SGetStaffListResultMsg.StaffItem staffItem = new SGetStaffListResultMsg.StaffItem();
                staffItem.setStaffId(item.getId());
                staffItem.setStaffName(item.getUserName());
                staffItem.setStaffAccount(item.getUserAccount());
                staffItem.setHeadImgUrl(item.getHeadImage());
                StaffGroup byId = staffGroupMapper.getById(item.getGroupId(), merId);
                Integer i = chatTalkSessionStaffRelService.countByStaffId(merId, item.getId());
                staffItem.setSessionCount(i);
                if (Objects.nonNull(byId)) {
                    staffItem.setGroupName(byId.getGroupName());
                }
                return staffItem;
            }).collect(Collectors.toList());
        }

        return Lists.newArrayList();
    }

    @PostMapping("/session/count")
    @ApiOperation(value = "会话数量统计", notes = "会话数量统计", response = SSessionCountResultMsg.class)
    public Object sessionCount(@RequestBody RSessionCountMsg content) {
        if (Objects.isNull(content) || Objects.isNull(content.getMerId()) || Objects.isNull(content.getStaffId())) {
            throw new BusinessException("参数错误");
        }
        Long merId = content.getMerId();
        Long staffId = content.getStaffId();

        List<Long> deviceUniqueIds = merchatChildDeviceRelationService.listDeviceUniqueIdByStaffId(merId, staffId);

        SSessionCountResultMsg sSessionCountResultMsg = new SSessionCountResultMsg();

        Integer i = chatTalkSessionStaffRelService.countByStaffId(merId, staffId);
        sSessionCountResultMsg.setNowSessionCount(i);
        Integer hang = chatTalkSessionStaffRelService.countHangWithStaffId(merId, staffId);
        sSessionCountResultMsg.setHangSessionCount(hang);

        MerchatChild byId = childMerchatService.getById(merId, staffId);
        if (Objects.isNull(byId)) {
            throw new BusinessException("员工不存在");
        }
        sSessionCountResultMsg.setTotalSessionCount(byId.getChatLimitCount());

        for (Long deviceUniqueId : deviceUniqueIds) {
            sSessionCountResultMsg.setOrderSessionCount(
                    sSessionCountResultMsg.getOrderSessionCount() + ObjectUtils.defaultIfNull(cacheHolder.countSessionOrder(merId, deviceUniqueId), 0)
            );
            sSessionCountResultMsg.setLeaveSessionCount(
                    sSessionCountResultMsg.getLeaveSessionCount() + ObjectUtils.defaultIfNull(cacheHolder.countSessionLeave(merId, deviceUniqueId), 0)
            );
        }

        return sSessionCountResultMsg;
    }

    @PostMapping("/session/leaveOrOrder/list")
    @ApiOperation(value = "会话排队/留言列表", notes = "会话排队/留言列表", response = Boolean.class)
    public Object sessionLeaveList(@RequestBody ROrderAndLeaveSessionListMsg content) {
        Long staffId = content.getStaffId();
        Long merId = content.getMerId();
        boolean order = Objects.equals(content.getType(), 1);
        List<Long> relDeviceUniqueIds = merchatChildDeviceRelationService.listDeviceUniqueIdByStaffId(merId, staffId);
        if (ObjectUtils.isEmpty(relDeviceUniqueIds)) {
            return Lists.newArrayList();
        }
        Page<?> page = new Page<>(content.getCurrent(), content.getSize());
        List<Long> allSessionIds = new ArrayList<>();
        for (Long relDeviceUniqueId : relDeviceUniqueIds) {
            List<Long> sessionIds = order ? cacheHolder.allSessionOrder(merId, relDeviceUniqueId) : cacheHolder.allSessionLeave(merId, relDeviceUniqueId);
            allSessionIds.addAll(sessionIds);
        }
        List<Long> sessionIds = CollUtil.sub(allSessionIds, (int) page.offset(), (int) (page.offset() + page.getSize()));

        List<ChatSessionDTO> records = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(sessionIds)) {
            List<ChatTalkSession> sessionList = chatTalkSessionService.listByIds(merId, sessionIds);
            for (ChatTalkSession chatTalkSession : sessionList) {
                if (Objects.nonNull(content.getChatType()) && !Objects.equals(chatTalkSession.getType(), content.getChatType())) {
                    continue;
                }
                ChatSessionDTO talkSessionMsg = chatTalkSessionService.convert(chatTalkSession);
                records.add(talkSessionMsg);
            }
        }
        return new Page<ChatSessionDTO>(page.getCurrent(), page.getSize(), allSessionIds.size()).setRecords(records);
    }

    @PostMapping("/session/leaveOrOrderAccept")
    @ApiOperation(value = "接入排队或留言的会话", notes = "接入排队或留言的会话", response = Boolean.class)
    public Object leaveOrOrderAccept(@RequestBody ROrderAndLeaveSessionAcceptMsg content) {
        //
        if (Objects.isNull(content) || ObjectUtils.isEmpty(content.getTalkSessionId()) || Objects.isNull(content.getType())) {
            throw new BusinessException("接入排队或留言参数错误");
        }
        List<Long> talkSessionIds = content.getTalkSessionId();
        Long staffId = content.getStaffId();
        Long merId = content.getMerId();
        Boolean order = Objects.equals(content.getType(), 1);
        //
        List<ChatTalkSession> sessionList = chatTalkSessionService.listByIds(merId, talkSessionIds);
        if (ObjectUtils.isEmpty(sessionList)) {
            throw new BusinessException("会话不存在");
        }
        //
        for (ChatTalkSession chatTalkSession : sessionList) {
            Long deviceUniqueId = chatTalkSession.getDeviceUniqueId();
            WwDevice device = wwDeviceService.getById(merId, deviceUniqueId);

            ChatTalkSessionStaffRel sessionStaffRel = chatTalkSessionStaffRelService.getByConvIdAndSessionId(merId, chatTalkSession.getConversationId(), chatTalkSession.getId());
            if (Objects.nonNull(sessionStaffRel) && !Objects.equals(sessionStaffRel.getStaffId(), staffId)) {
                throw new BusinessException("当前聊天:" + chatTalkSession.getConversationName() + ", 已分发到其他员工, 请重新选择");
            }
            chatTalkSessionStaffRelService.addIfAbsentV1(merId, chatTalkSession, staffId, false);

            Long lastRecvId = chatTalkSession.getLastRecvId();

            ChatTalkRecord chatTalkRecord = null;
            if (Objects.nonNull(lastRecvId)) {
                chatTalkRecord = chatTalkRecordService.getById(merId, lastRecvId);
            }
            String staffTag = cacheHolder.getStaffTag(staffId);
            if (StringUtils.isBlank(staffTag)) {
                throw new BusinessException("当前员工未上线, 无法接受会话");
            }
            if (order) {
                cacheHolder.delSessionOrder(merId, deviceUniqueId, chatTalkSession.getId());
            } else {
                cacheHolder.delSessionLeave(merId, deviceUniqueId, chatTalkSession.getId());
            }

            SendDTO sendDTO = new SendDTO();
            sendDTO.setStaffId(staffId);
            sendDTO.setTalkSessionId(chatTalkSession.getId());
            sendDTO.setTalkRecordId(chatTalkRecord.getId());
            sendDTO.setMerId(merId);
            sendDTO.setStaffTag(staffTag);

            SendMQDTO sendMQDTO = new SendMQDTO();
            sendMQDTO.setType(MQMsgType.push_talk.getCode());
            sendMQDTO.setData(sendDTO);

            log.info("接受会话的员工未在当前节点, 路由到目标节点: {}", JSON.toJSONString(sendDTO));
            MQSender.sendMQMsg("XJ_WW_DISPATCH_HANDLE_TOPIC:" + staffTag, sendMQDTO);
        }
        return true;
    }

    @PostMapping("/session/leaveOrOrderRemove")
    @ApiOperation(value = "移除排队或留言的会话", notes = "移除排队或留言的会话", response = Boolean.class)
    public Object leaveOrOrderRemove(@RequestBody ROrderAndLeaveSessionRemoveMsg content) {
        //
        if (Objects.isNull(content) || ObjectUtils.isEmpty(content.getTalkSessionId()) || Objects.isNull(content.getType())) {
            throw new BusinessException("接入排队或留言参数错误");
        }
        List<Long> talkSessionIds = content.getTalkSessionId();
        Long staffId = content.getStaffId();
        Long merId = content.getMerId();
        Boolean order = Objects.equals(content.getType(), 1);
        //
        List<ChatTalkSession> sessionList = chatTalkSessionService.listByIds(merId, talkSessionIds);
        if (ObjectUtils.isEmpty(sessionList)) {
            throw new BusinessException("会话不存在");
        }
        for (ChatTalkSession chatTalkSession : sessionList) {
            if (order) {
                cacheHolder.delSessionOrder(merId, chatTalkSession.getDeviceUniqueId(), chatTalkSession.getId());
            } else {
                cacheHolder.delSessionLeave(merId, chatTalkSession.getDeviceUniqueId(), chatTalkSession.getId());
            }
        }
        return true;
    }
}
